package com.goldcn.user.service;

import com.goldcn.common.consts.RestConst;
import com.goldcn.common.exception.ServiceException;
import com.goldcn.common.util.CommonUtils;
import com.goldcn.common.util.IdGen;
import com.goldcn.interceptor.SystemContext;
import com.goldcn.user.dao.CompanyInfoMapper;
import com.goldcn.user.dao.UserInfoMapper;
import com.goldcn.user.dao.UserLoginMapper;
import com.goldcn.user.dao.WechatAuthMapper;
import com.goldcn.user.dto.WechatAuthDTO;
import com.goldcn.user.model.*;
import com.google.common.base.Objects;
import com.sun.jersey.core.util.Base64;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
import java.util.Arrays;


/**
 * Created by 1111 on 2016/11/8.
 */
@Service
@Transactional
public class UserAuthService {

    @Autowired
    WechatAuthMapper wechatAuthMapper;
    @Autowired
    UserInfoMapper userInfoMapper;
    @Autowired
    UserInfoService userInfoService;
    @Autowired
    OrganizationalService organizationalService;
    @Autowired
    CompanyInfoMapper companyInfoMapper;
    @Autowired
    UserLoginMapper userLoginMapper;

    @Autowired
    RestTemplate restTemplate;

    private Logger logger = Logger.getLogger(UserAuthService.class);


    /**
     * 新增微信用户授权
     *
     * @param wechatAuth
     * @return
     */
    public Object addUserByWechatAuth(WechatAuthDTO wechatAuth) {
        Long usrID = getUserByWechatAuth(wechatAuth);
        if (usrID != null) {
            return userInfoService.selectByUserID(usrID);
        }
        Long curTime = CommonUtils.getCurTimestamp();
        UserInfo userInfo = new UserInfo();
        userInfo.setType(4);
        String sessionKey = wechatAuth.getUnionid();

        JSONObject phoneJson = this.getWechatDataInfo(wechatAuth.getPhone(), sessionKey, wechatAuth.getRemark());
        logger.info(phoneJson);
        if (phoneJson == null || phoneJson.getString("phoneNumber") == null || phoneJson.getString("phoneNumber").length() == 0) {
            logger.error("获取微信phone异常,没有找到phone");
            throw new ServiceException("网络服务异常", RestConst.ErrorCode.SERVICE_FAIL);
        }
        wechatAuth.setPhone(phoneJson.getString("phoneNumber"));
        wechatAuth.setRemark(null);
        wechatAuth.setSource(null);
        wechatAuth.setUnionid(null);

        //登录表保存相关信息
        UserLogin userLogin = new UserLogin();
        userLogin.setPassWord(wechatAuth.getOwnerID()); // wechat appid
        userLogin.setCompanyID(SystemContext.getCompanyID());
        userLogin.setId(IdGen.get().nextId());
        userLogin.setLoginName(wechatAuth.getOpenID()); // wechat user openid

        WechatAuth wechatAuthObj = (WechatAuth) wechatAuth;
        wechatAuthObj.setBindUserID(IdGen.get().nextId() + "");
        wechatAuthObj.setAddTime(curTime);
        wechatAuthObj.setUpdateTime(curTime);
        wechatAuthObj.setSource("wechat minipro");

        UserLogin loginAccount = userLoginMapper.selectLoginName(wechatAuth.getPhone(), SystemContext.getCompanyID());
        if (loginAccount == null) {
            userInfo.setUserID(IdGen.get().nextId());
            userInfo.setAccount(wechatAuth.getPhone());
            userInfo.setMobile(wechatAuth.getPhone());
            userInfo.setIsStop(0);
            userInfo.setAddTime(curTime);
            userInfo.setUpdateTime(curTime);
            userInfo.setCompanyID(SystemContext.getCompanyID());
            userInfo.setPassWord("30b995b48f72102fb2645999d82aa245"); //a123456
            userInfo.setState(1);
            userInfo.setIsAdmin(2);
            userInfo.setNickName(wechatAuth.getNickName());
            userInfo.setSex(wechatAuth.getSex());
            userInfo.setName(wechatAuth.getPhone().length() > 4 ? "**" + StringUtils.right(wechatAuth.getPhone(), 4) : wechatAuth.getPhone());
            //会员注册需要查询推荐人信息,如果不填推荐码则会员归属于总行直属会员
            if (wechatAuth.getRecommendCode() == null) {
                Organizational organizational = organizationalService.selectHeadCCB(SystemContext.getCompanyID());
                userInfo.setOrganizationalID(organizational.getoID());
                userInfo.setPaterID(Long.parseLong("0"));
                userInfo.setShopID(wechatAuth.getShopID());
            } else {
                UserInfo userRecommender = userInfoService.selectByUserID(Long.parseLong(wechatAuth.getRecommendCode()));
                if (userRecommender == null) {
                    logger.error("推荐码不存在:" + wechatAuth.getRecommendCode());
                    Organizational organizational = organizationalService.selectHeadCCB(SystemContext.getCompanyID());
                    userInfo.setOrganizationalID(organizational.getoID());
                    userInfo.setPaterID(Long.parseLong("0"));
                } else {
                    //获取推荐人的userID
                    userInfo.setOrganizationalID(userRecommender.getOrganizationalID());
                    userInfo.setPaterID(userRecommender.getUserID());
                    userInfo.setShopID(userRecommender.getShopID());
                }
            }
            userLogin.setUserID(userInfo.getUserID());
            wechatAuthObj.setUserID(userInfo.getUserID());

            //用户不存在,则为全新会员
            userInfoMapper.insertSelective(userInfo);

            //新会员送金豆处理
            userInfoService.setManagerPoint(userInfo);

            //使用手机可登录
            UserLogin userwxLogin = new UserLogin();
            userwxLogin.setPassWord("30b995b48f72102fb2645999d82aa245"); //a123456
            userwxLogin.setCompanyID(SystemContext.getCompanyID());
            userwxLogin.setId(IdGen.get().nextId());
            userwxLogin.setUserID(userInfo.getUserID());
            userwxLogin.setLoginName(wechatAuth.getPhone());
            userLoginMapper.insertSelective(userwxLogin);

        } else {
            //系统已经存在的用户，绑定用户授权信息
            userLogin.setUserID(loginAccount.getUserID());
            wechatAuthObj.setUserID(loginAccount.getUserID());

            userInfo = userInfoService.selectByUserID(loginAccount.getUserID());
        }
        userLoginMapper.insertSelective(userLogin);
        wechatAuthMapper.insertSelective(wechatAuthObj);

        userInfo.setPassWord(null);

        return userInfo;
    }

    /**
     * @param wechatAuthDTO
     * @return
     */
    public Long getUserByWechatAuth(WechatAuthDTO wechatAuthDTO) {

        String openId = wechatAuthDTO.getOpenID();
        String ownerID = wechatAuthDTO.getOwnerID();

        Long userId = wechatAuthMapper.getUserByOpenId(openId, ownerID);
        if (userId != null) {
            return userId;
        }
        return null;
    }


    //根据用户查找shopID，员工可能userInfo表shopID为空情况
    public Long getShopIDByUserID(Long userID) {
        UserInfo userInfo = userInfoMapper.selectByPrimaryKey(userID);
        Long shopID = userInfo.getShopID();
        if (shopID == null || Objects.equal(shopID, 0l)) {
            CompanyInfo companyInfo = companyInfoMapper.getMallInfo(userInfo.getOrganizationalID());
            shopID = companyInfo.getCompanyInfoID();
        }

        return shopID;

    }

    /**
     * 解密wx用户敏感数据
     *
     * @param sessionKey    数据进行加密签名的密钥
     * @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
     * @param iv            加密算法的初始向量
     * @return
     * @author admin
     */
    public JSONObject getWechatDataInfo(String encryptedData, String sessionKey, String iv) {
        // 被加密的数据
        byte[] dataByte = Base64.decode(encryptedData);
        // 加密秘钥
        byte[] keyByte = Base64.decode(sessionKey);
        // 偏移量
        byte[] ivByte = Base64.decode(iv);
        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                return JSONObject.fromObject(result);
            }
        } catch (NoSuchAlgorithmException e) {
            logger.error(e.getMessage(), e);
        } catch (NoSuchPaddingException e) {
            logger.error(e.getMessage(), e);
        } catch (InvalidParameterSpecException e) {
            logger.error(e.getMessage(), e);
        } catch (IllegalBlockSizeException e) {
            logger.error(e.getMessage(), e);
        } catch (BadPaddingException e) {
            logger.error(e.getMessage(), e);
        } catch (UnsupportedEncodingException e) {
            logger.error(e.getMessage(), e);
        } catch (InvalidKeyException e) {
            logger.error(e.getMessage(), e);
        } catch (InvalidAlgorithmParameterException e) {
            logger.error(e.getMessage(), e);
        } catch (NoSuchProviderException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

}
